/**
 * Created by yiwei on 2017/09/28.
 * fetch 中间件
 */
import fetch from 'isomorphic-fetch';
import info from '../config/info';

const fetchOptions = {
    method: 'post',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin':'*',
        'Access-Control-Allow-Credentials':'true',
        'Access-Token': sessionStorage.getItem('token') || '' // 从sessionStorage中获取token
    },
    credentials: 'same-origin',
};
const loadingOptions = {
    show: false,
    tip: '',
};
/**
 * fetch 超时响应封装，只通过中间件的才生效。
 * @param fetchPromise   fetch对象
 * @param timeout 请求超时时间，默认50秒，后端超时时间为50秒
 * @return {Promise.<*>}
 * @private
 */
let fetchTimeout = null;

function fetchMayTimeout(fetchPromise, timeout) {
    let abortFn = null;
    // 这是一个可以被reject的promise
    const abortPromise = new Promise((resolve, reject) => {
        abortFn = () => {
            reject({
                status: {
                    code: 408,
                    message: '请求超时',
                },
            });
        };
    });
    // 这里使用Promise.race，以最快 resolve 或 reject 的结果来传入后续绑定的回调
    const abortablePromise = Promise.race([
        fetchPromise,
        abortPromise,
    ]);
    clearTimeout(fetchTimeout);
    fetchTimeout = setTimeout(() => {
        abortFn();
    }, timeout);
    return abortablePromise;
}

const defaultSuffix = ['Request', 'Success', 'Failure'];
/* eslint-disable no-unused-vars */
export default ({dispatch, getState}) => next => (action) => {
    /* eslint-disable no-unused-vars */
    if (!action || !action.fetchPayload || !action.fetchPayload.url) {
        return next(action);
    }
    const type = action.type;
    const payload = action.fetchPayload;
    const url = payload.url;
    const conditionFun = payload.condition; // 条件
    const success = payload.success; // TODO 添加成功的回调，这样是否合适？
    const loading = {...loadingOptions, ...payload.loadingOptions};  // 是否需要LOADING
    const options = payload.options;
    const opts = {...fetchOptions, ...options};
    const paulPayload = action.payload;

    if (loading.show) dispatch({type: 'showLoading', payload: loading.tip, meta: '显示loading'});

    dispatch({type: type + defaultSuffix[0]});

    fetchMayTimeout(fetch(url, opts), 50000)
        .then(response => response.json())
        .then((json) => {
        if (json && json.code === 1200) { // 登录超时
            window.location.href = `#${info.base.name}userLogin/noLogin`;
            return;
        }
        if (conditionFun) {
            if (conditionFun(json)) {
            dispatch({type: type + defaultSuffix[1], payload: {...json, ...paulPayload}, meta: '异步请求成功'});
            if (success) success(dispatch);
            } else {
                dispatch({
                    type: type + defaultSuffix[2],
                    payload: {...json, ...paulPayload},
                    meta: '异步请求成功，但判断条件（condition）失败',
                });
            }
        } else {
            dispatch({type: type + defaultSuffix[1], payload: {...json, ...paulPayload}, meta: '异步请求成功'});
            if (success) success(dispatch);
        }
        if (loading.show) dispatch({type: 'hideLoading', meta: '隐藏loading'});
        })
        .catch((e) => {
            console.log(`------------------------------error at fetch ---->type: > ${type} <`);
            console.info(e);
            console.log('------------------------------');
            if (loading.show) dispatch({type: 'hideLoading', meta: '隐藏loading'});
            dispatch({type: type + defaultSuffix[2], payload: e, meta: '异步请求失败'});
        });
};
